package com.yubest.demo.anno;

import com.yubest.demo.anno.handler.*;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Author hweiyu
 * @Description
 * @Date 2021/3/23 10:48
 */
@Aspect
@Component
public class RequestProcess {

    /**
     * 拦截的注解
     */
    @Pointcut("@annotation(com.yubest.demo.anno.Log) " +
            "|| @annotation(com.yubest.demo.anno.Login) " +
            "|| @annotation(com.yubest.demo.anno.Repeat)")
    public void point() { }

    @Around("point()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        //获取request对象
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        String uri = request.getRequestURI();

        Map<String, String> headerMap = new HashMap<>(16);
        Enumeration<String> headers = request.getHeaderNames();
        //获取请求头
        while (headers.hasMoreElements()) {
            String name = headers.nextElement();
            headerMap.put(name, request.getHeader(name));
        }

        //获取方法
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = pjp.getTarget().getClass().getDeclaredMethod(methodSignature.getMethod().getName(),
                methodSignature.getMethod().getParameterTypes());

        List<String> argNames = new ArrayList<>(10);
        List<Object> argValues = new ArrayList<>(10);

        //获取方法的参数名称
        String[] params = new LocalVariableTableParameterNameDiscoverer().getParameterNames(method);
        //获取方法的参数值
        Object[] paramValues = pjp.getArgs();
        if (null != params) {
            for (int i = 0; i < params.length; i++) {
                if (paramValues[i] instanceof MultipartFile
                        || paramValues[i] instanceof HttpServletRequest
                        || paramValues[i] instanceof HttpServletResponse) {
                    continue;
                }
                argNames.add(params[i]);
                argValues.add(paramValues[i]);
            }
        }

        //封装请求信息
        Context context = new Context()
                .setUri(uri)
                .setMethod(method)
                .setArgNames(argNames)
                .setArgValues(argValues)
                .setHeaders(headerMap);

        //拦截处理器进行请求处理
        new HanlderChain()
                //@see com.yubest.demo.anno.handler.LogHandler
                .register(new LogHandler())
                //@see com.yubest.demo.anno.handler.RepeatHandler
                .register(new RepeatHandler())
                //@see com.yubest.demo.anno.handler.LoginHandler
                .register(new LoginHandler())
                .execute(context);

        return pjp.proceed();
    }

}
